#include "iConfig.hpp"
#include <glf/task/taskDirector.h>
#include <glf/task/taskThread.h>
#include <glf/task/taskHandler.h>

namespace glf {

TaskDirector* TaskDirector::s_TaskDirectorInstance = NULL;
int TaskDirector::s_Lock = 0;


TaskDirector::TaskDirector()
{
}

TaskDirector::~TaskDirector()
{
}

TaskDirector& TaskDirector::GetInstance()
{
	if(!s_TaskDirectorInstance)
	{
		while(AtomicCompareAndSwap(s_Lock, 1, 0) != 0) 
		{
			Thread::Sleep(1);
		}

		if(!s_TaskDirectorInstance)
		{
			TaskDirector* temp = new TaskDirector;
			Membar();
			s_TaskDirectorInstance = temp;
		}

		StoreWithRelease(s_Lock, 0);
	}

	return *s_TaskDirectorInstance;
}

void TaskDirector::StopThread(ThreadList& tl)
{
	for(int i = 0; i < tl.m_Count; ++i)
	{
		tl.m_Thread[i]->Stop();
		m_DeleteList.push_back(tl.m_Thread[i]);
	}
	tl.m_Count = 0;
}	

bool TaskDirector::CleanUp()
{
	for(DeleteList::iterator i = m_DeleteList.begin(), end = m_DeleteList.end(); i != end;)
	{
		if((*i)->GetStatus() == Thread::STATUS_STOPPED)
		{
			(*i)->Join();
			delete *i;

			m_DeleteList.erase(i++);
		}
		else
		{
			++i;
		}
	}
	return m_DeleteList.empty();
}

void TaskDirector::RemoveUnused()
{
}

void TaskDirector::RegisterHandler(TaskHandlerBase* th, ThreadId id)
{
	TaskHandlerList& thl = m_TaskHandlerMap[id];
	thl.push_back(th);
}

void TaskDirector::UnregisterHandler(TaskHandlerBase* th, ThreadId id)
{
	TaskHandlerList& thl = m_TaskHandlerMap[id];
	thl.remove(th);
}

bool TaskDirector::IsEquivalentHandlerRegistered(TaskHandlerBase* th)
{
	TaskHandlerMap::iterator thi = m_TaskHandlerMap.find(GetCurrentThreadId());
	if(thi != m_TaskHandlerMap.end())
	{
		TaskHandlerList& thl = thi->second;
		for(TaskHandlerList::iterator i = thl.begin(), end = thl.end(); i != end; ++i)
		{
			if ((*i)->IsEquivalent(th))
			{
				return true;
			}
		}
	}
	return false;
}

bool TaskDirector::ConsumeRegisteredHandler()
{
	TaskHandlerList& thl = m_TaskHandlerMap[GetCurrentThreadId()];

	bool hasPendingTask = false;
	for(TaskHandlerList::iterator i = thl.begin(), end = thl.end(); i != end; ++i)
	{
		hasPendingTask |= (*i)->Consume();
	}

	return hasPendingTask;
}

} // end namespace glf
